/*
 * FXGL - JavaFX Game Library. The MIT License (MIT).
 * Copyright (c) AlmasB (almaslvl@gmail.com).
 * See LICENSE for details.
 */

package com.windea.study.kotlin.fxgl.sample.sandbox.saving

import com.almasb.fxgl.app.*
import com.almasb.fxgl.core.serialization.*
import com.almasb.fxgl.dsl.*
import com.almasb.fxgl.entity.*
import com.almasb.fxgl.input.*
import com.almasb.fxgl.saving.*
import javafx.geometry.*
import javafx.scene.input.*
import javafx.scene.paint.*
import javafx.scene.shape.*
import java.util.*

/**
 * Shows how to save and load game state.
 */
class SaveSample : GameApplication() {
	private lateinit var player: Entity
	private lateinit var enemy: Entity
	private lateinit var playerControl: PlayerControl
	
	// 1. the data to save/load
	private lateinit var playerPosition: Point2D
	private lateinit var enemyPosition: Point2D
	
	private enum class Type {
		PLAYER, ENEMY
	}
	
	override fun initSettings(settings: GameSettings) {
		settings.width = 800
		settings.height = 600
		settings.title = "SaveSample"
		settings.version = "0.1"
		settings.isMenuEnabled = true
		settings.enabledMenuItems = EnumSet.allOf(MenuItem::class.java)
	}
	
	// while this will be called on "new" game
	override fun initGame() {
		initGame(Point2D(100.0, 100.0), Point2D(200.0, 100.0))
	}
	
	private fun initGame(playerPos: Point2D, enemyPos: Point2D) {
		playerPosition = playerPos
		enemyPosition = enemyPos
		
		player = entityBuilder()
			.type(Type.PLAYER)
			.at(playerPosition)
			.view(Rectangle(40.0, 40.0, Color.BLUE))
			.build()
		
		playerControl = PlayerControl()
		player.addComponent(playerControl)
		
		enemy = Entity()
		//        enemy.getTypeComponent().setValue(Type.ENEMY);
		//        enemy.getPositionComponent().setValue(enemyPosition);
		//        enemy.getViewComponent().setView(new EntityView(new Rectangle(40, 40, Color.RED)));
		
		getGameWorld().addEntities(player, enemy)
	}
	
	override fun initInput() {
		val input = getInput()
		
		input.addAction(object : UserAction("Move Left") {
			override fun onAction() {
				playerControl.left()
			}
		}, KeyCode.A)
		
		input.addAction(object : UserAction("Move Right") {
			override fun onAction() {
				playerControl.right()
			}
		}, KeyCode.D)
		
		input.addAction(object : UserAction("Move Up") {
			override fun onAction() {
				playerControl.up()
			}
		}, KeyCode.W)
		
		input.addAction(object : UserAction("Move Down") {
			override fun onAction() {
				playerControl.down()
			}
		}, KeyCode.S)
		
		input.addAction(object : UserAction("Rotate") {
			override fun onAction() {
				player.rotateBy(1.0)
			}
		}, KeyCode.F)
		
		input.addAction(object : UserAction("Switch Types") {
			override fun onAction() {
				if(player.typeComponent.isType(Type.PLAYER)) {
					player.typeComponent.value = Type.ENEMY
					enemy.typeComponent.value = Type.PLAYER
				} else {
					player.typeComponent.value = Type.PLAYER
					enemy.typeComponent.value = Type.ENEMY
				}
			}
		}, KeyCode.G)
	}
	
	// 2. override and specify how to serialize
	public override fun saveState(): DataFile {
		
		val bundlePlayer = Bundle("Player")
		val bundleEnemy = Bundle("Enemy")
		
		//player.save(bundlePlayer);
		//enemy.save(bundleEnemy);
		
		val bundleRoot = Bundle("Root")
		bundleRoot.put("player", bundlePlayer)
		bundleRoot.put("enemy", bundleEnemy)
		
		return DataFile(bundleRoot)
	}
	
	// 3. override and specify how to deserialize
	// this will be called on "load" game
	public override fun loadState(dataFile: DataFile) {
		
		// call "new" initGame
		initGame()
		
		// now load state back
		val bundleRoot = dataFile.data as Bundle
		
		println(player)
		println(enemy)
		
		//player.load(bundleRoot.get("player"));
		//enemy.load(bundleRoot.get("enemy"));
		
		println(player)
		println(enemy)
	}
}


fun main(args: Array<String>) {
	GameApplication.launch(SaveSample::class.java, args)
}

